#include "FileDownLoad.h"
#include "Sigin.h"
#include "CryptoUtil.h"
#include <nlohmann/json.hpp>
#include <workflow/MySQLResult.h>
#include <wfrest/PathUtil.h>
#include <unistd.h>
#include <map>
#include <string>
#include <sstream>
#include <iostream>
#include <functional>
using std::map;
using std::string;
using std::function;
using std::ostringstream;
using std::bind;
using namespace protocol;
using namespace wfrest;

using JSON = nlohmann::json;

FileDownLoad::FileDownLoad(wfrest::HttpServer & server)
:m_server(server)
{

}

void pread_callback(WFFileIOTask *task){
    FileIOArgs *args = task->get_args();
    long ret = task->get_retval();
    HttpResponse *resp = (HttpResponse *)task->user_data;

    close(args->fd);
    if (ret < 0)
    {
        resp->set_status_code("503");
        resp->append_output_body("<html>503 Internal Server Error.</html>");
    }
    else{
        resp->append_output_body_nocopy(args->buf, ret);
    }
}

void FileDownLoad::fileDownload_module(){
    m_server.GET("/file/download",[](const HttpReq* req, HttpResp* resp,SeriesWork* series){
        string username;
        string token;
        string filename;
        string filehash;
        username = req->query("username");
        token = req->query("token");
        filename = req->query("filename");
        filehash = req->query("filehash");
        
        string filePath = "./file/"+filehash;

        if(CryptoUtil::verify_token(token,username)){
            int fd = ::open(filePath.c_str(),O_RDONLY);
            size_t size = lseek(fd, 0, SEEK_END);
            char * buf = (char *)malloc(size);        
            WFFileIOTask *pread_task;

            pread_task = WFTaskFactory::create_pread_task(fd, buf, size, 0, pread_callback);
           
            pread_task->user_data = resp;    
            series->set_callback([buf](const SeriesWork *){  free(buf); });
            
            series->push_back(pread_task);
        }
    });    
}

void FileDownLoad::start(){
    fileDownload_module();
}
